<?php

/*
  Plugin Name: Auto Post News
  Plugin URI: http://ootv.tk/
  Description: 按照既定规则自动采集你需要的网站的新闻并发表到你的博客.
  Version: 0.1.11.3.21
  Author: 最爱你是谁
  Author URI: http://ootv.tk/
 */

/*  Copyright 2010 最爱你是谁  (email : 023yangbo@gmail.com)

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
if (! function_exists ( 'add_action' )) {
	require '../../../wp-load.php';
	echo post_news ();
}

/**
 * 检查锁定或删除锁定
 * @package WordPress
 * @subpackage Auto-Post-News
 * @since 0.0.1
 * @param string $action check|delete 执行任务种类，检查或删除
 * @param string $lock_file 锁文件路径
 * @return mixed TRUE（锁定）|FALSE（未锁定）
 */
function lock($action, $lock_file) {
	//	chmod ( dirname ( $lock_file ), 0751 );
	if ($action == 'check') :
		if (! file_exists ( $lock_file )) {
			$post_lock = fopen ( $lock_file, 'w' );
			fwrite ( $post_lock, time () );
			fclose ( $post_lock );
			return 'unlock';
		}
		$lock_time = trim ( file_get_contents ( $lock_file ) );
		if (is_numeric ( $lock_time ) && time () - $lock_time <= 900) {
			//任务异常中断判断,此时间应当预估要超过执行任务所需时间
			return 'locked';
		}
		$post_lock = fopen ( $lock_file, 'w' );
		fwrite ( $post_lock, time () );
		fclose ( $post_lock );
		return 'unlock';
	 elseif ($action == 'delete') :
		if (file_exists ( $lock_file )) {
			unlink ( $lock_file );
			return 'Lock file deleted.';
		} else {
			return 'Lock file not found!';
		}
	 else :
		return 'Don\'t be kid. What did you want?';
	endif;
}

/**
 * 获取所有文章的guid
 * @package WordPress
 * @subpackage Auto-Post-News
 * @since 0.0.1
 * @param array $args 与get_posts相同
 * @return array 包含所有guid
 */
function get_guids($args = null) {
	//使用与get_posts相同的变量，返回guid数组
	$posts = get_posts ( $args );
	if (empty ( $posts )) {
		return $posts;
	}
	foreach ( $posts as $post ) {
		$guids [] = esc_url ( $post->guid );
	}
	return $guids;
}

/**
 * 将URL相对路径更改为绝对路径
 * @package WordPress
 * @subpackage Auto-Post-News
 * @since 0.0.1
 * @param string $link 包含链接的内容
 * @param string $url 包含完整链接的URL
 * @return string 包含完整链接的内容
 */
function make_link_absolute($link, $url) {
	preg_match ( '|(https?://[^/]+/).*|i', $url, $siteroot );
	return preg_replace ( '|(<a[^>]*?href=["\']?)/([^"\']*["\']?)|i', "$1" . $siteroot ['1'] . "$2", $link );
}

/**
 * 自定义替换
 * @package WordPress
 * @subpackage Auto-Post-News
 * @since 0.0.1
 * @param string $content 需要替换的内容
 * @param array $str_replace 普通替换规则
 * @param array $preg_replace 正则替换规则
 * @return string 替换后内容
 */
function custom_replace($content, $str_replace, $preg_replace) {
	foreach ( $str_replace as $pattern ) {
		$content = str_ireplace ( $pattern, '', $content );
	}
	foreach ( $preg_replace as $pattern ) {
		$content = preg_replace ( $pattern, '', $content );
	}
	return $content;
}

/**
 * 获取指定地址全文内容
 * @package WordPress
 * @subpackage Auto-Post-News
 * @since 0.0.1
 * @param string $news_url 地址
 * @return mixed $news 成功则全文内容，否则返回false
 */
function get_news($news_url) {
	$ch = curl_init ( $news_url );
	curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, TRUE );
	$news = curl_exec ( $ch );
	$count_curl = 0;
	while ( empty ( $news ) && $count_curl <= 5 ) {
		$count_curl ++;
		sleep ( '3' );
		$news = curl_exec ( $ch );
	}
	curl_close ( $ch );
	return $news;
}

/**
 * 依据给定的地址和规则采集并发表文章
 * @package WordPress
 * @subpackage Auto-Post-News
 * @since 0.0.1
 * @param array $news_args 所有需要用到的参数，参考示例
 * @return bool 成功则返回文章ID，失败则返回具体原因
 */
function post_news() {
	$news_args = array ('lock_file' => dirname ( __FILE__ ) . '/post.lock', 'news_list_type' => 'rss', 'news_rss' => 'http://feeds.bbci.co.uk/news/business/rss.xml', 'news_max' => 2, 'auto_matche' => FALSE, 'news_pattern' => array (array ('<!-- / story-body -->', '|<h1 class="story-header">([\W\w]*?)</h1>([\W\w]*?)</div><!-- / story-body -->|i' ), array ('<div id="page-bookmark-links-foot"', '|<h1 class="story-header">([\W\w]*?)</h1>([\W\w]*?)<div id="page-bookmark-links-foot"|i' ), array ('<table class="storycontent"', '|<table class="storycontent"[\W\w]*?<h1>([\W\w]*?)</h1>([\W\w]*?)<!-- body - End -->|i' ) ), 'preg_replace' => array ('|<noscript>[\W\w]*?</noscript>|i', '|<script[\W\w]*?</script>|i', '|<form[\W\w]*?</form>|i', '|<ul class="related-links-list">[\W\w]*?</ul>|i', '|<!--[\W\w]*?-->|i', '|<[a-z][^>]*></[^>]*>|i', '|<div class="read-more">[\W\w]*?</div>|i' ), 'str_replace' => array ("\n", "\t", "\r", "\0", "\x0B", '  ', 'Continue reading the main story' ), 'has_content_post' => 'publish', 'no_content_post' => 'draft', 'author' => '1', 'category_name' => 'Business', 'rss_time' => FALSE, 'add_more' => array (TRUE, 1000, 500 ), 'publish_time' => TRUE, 'orgin_link' => TRUE );
	if (lock ( 'check', $news_args ['lock_file'] ) == 'locked') {
		return 'Locked';
	}
	ignore_user_abort ( TRUE );
	$rss = fetch_feed ( $news_args ['news_rss'] );
	if (! is_wp_error ( $rss )) {
		$items = $rss->get_items ();
	} else {
		lock ( 'delete', $news_args ['lock_file'] );
		return $rss;
	}
	$post_guids = get_guids ( 'numberposts=50&post_status=publish,draft' );
	$allowedposttags = array ('address' => array (), 'a' => array ('href' => array (), 'id' => array (), 'title' => array (), 'rel' => array (), 'rev' => array (), 'name' => array (), 'target' => array () ), 'abbr' => array ('title' => array () ), 'acronym' => array ('title' => array () ), 'article' => array ('align' => array (), 'dir' => array (), 'lang' => array (), 'xml:lang' => array () ), 'aside' => array ('align' => array (), 'dir' => array (), 'lang' => array (), 'xml:lang' => array () ), 'b' => array (), 'big' => array (), 'blockquote' => array ('id' => array (), 'cite' => array (), 'lang' => array (), 'xml:lang' => array () ), 'br' => array ('class' => array () ), 'caption' => array ('align' => array (), 'class' => array () ), 'cite' => array ('dir' => array (), 'lang' => array (), 'title' => array () ), 'code' => array (), 'col' => array ('align' => array (), 'char' => array (), 'charoff' => array (), 'span' => array (), 'dir' => array (), 'valign' => array (), 'width' => array () ), 'del' => array ('datetime' => array () ), 'dd' => array (), 'details' => array ('align' => array (), 'dir' => array (), 'lang' => array (), 'open' => array (), 'xml:lang' => array () ), 'dl' => array (), 'dt' => array (), 'em' => array (), 'figure' => array ('align' => array (), 'dir' => array (), 'lang' => array (), 'xml:lang' => array () ), 'figcaption' => array ('align' => array (), 'dir' => array (), 'lang' => array (), 'xml:lang' => array () ), 'font' => array ('color' => array (), 'face' => array (), 'size' => array () ), 'footer' => array ('align' => array (), 'dir' => array (), 'lang' => array (), 'xml:lang' => array () ), 'h1' => array ('align' => array (), 'id' => array () ), 'h2' => array ('align' => array (), 'id' => array () ), 'h3' => array ('align' => array (), 'id' => array () ), 'h4' => array ('align' => array (), 'id' => array () ), 'h5' => array ('align' => array (), 'id' => array () ), 'h6' => array ('align' => array (), 'id' => array () ), 'header' => array ('align' => array (), 'dir' => array (), 'lang' => array (), 'xml:lang' => array () ), 'hgroup' => array ('align' => array (), 'dir' => array (), 'lang' => array (), 'xml:lang' => array () ), 'hr' => array ('align' => array (), 'noshade' => array (), 'size' => array (), 'width' => array () ), 'i' => array (), 'img' => array ('alt' => array (), 'align' => array (), 'border' => array (), 'height' => array (), 'hspace' => array (), 'longdesc' => array (), 'vspace' => array (), 'src' => array (), 'width' => array () ), 'ins' => array ('datetime' => array (), 'cite' => array () ), 'kbd' => array (), 'li' => array ('align' => array (), 'class' => array () ), 'menu' => array ('type' => array () ), 'p' => array ('align' => array (), 'dir' => array (), 'lang' => array (), 'xml:lang' => array () ), 'pre' => array ('width' => array () ), 'q' => array ('cite' => array () ), 's' => array (), 'span' => array ('dir' => array (), 'align' => array (), 'lang' => array (), 'title' => array (), 'xml:lang' => array () ), 'section' => array ('align' => array (), 'dir' => array (), 'lang' => array (), 'xml:lang' => array () ), 'strike' => array (), 'strong' => array (), 'sub' => array (), 'summary' => array ('align' => array (), 'dir' => array (), 'lang' => array (), 'xml:lang' => array () ), 'sup' => array (), 'table' => array ('align' => array (), 'bgcolor' => array (), 'border' => array (), 'cellpadding' => array (), 'cellspacing' => array (), 'dir' => array (), 'id' => array (), 'rules' => array (), 'summary' => array (), 'width' => array () ), 'tbody' => array ('align' => array (), 'char' => array (), 'charoff' => array (), 'valign' => array () ), 'td' => array ('abbr' => array (), 'align' => array (), 'axis' => array (), 'bgcolor' => array (), 'char' => array (), 'charoff' => array (), 'colspan' => array (), 'dir' => array (), 'headers' => array (), 'height' => array (), 'nowrap' => array (), 'rowspan' => array (), 'scope' => array (), 'valign' => array (), 'width' => array () ), 'tfoot' => array ('align' => array (), 'char' => array (), 'charoff' => array (), 'valign' => array () ), 'th' => array ('abbr' => array (), 'align' => array (), 'axis' => array (), 'bgcolor' => array (), 'char' => array (), 'charoff' => array (), 'colspan' => array (), 'headers' => array (), 'height' => array (), 'nowrap' => array (), 'rowspan' => array (), 'scope' => array (), 'valign' => array (), 'width' => array () ), 'thead' => array ('align' => array (), 'char' => array (), 'charoff' => array (), 'valign' => array () ), 'title' => array (), 'tr' => array ('align' => array (), 'bgcolor' => array (), 'char' => array (), 'charoff' => array (), 'valign' => array () ), 'tt' => array (), 'u' => array (), 'ul' => array ('type' => array () ), 'ol' => array ('start' => array (), 'type' => array () ), 'video' => array ('autoplay' => array (), 'controls' => array (), 'height' => array (), 'loop' => array () ), 'preload' => array (), 'src' => array (), 'width' => array () );
	$count_post = 0;
	foreach ( $items as $item ) :
		$news_matche = array ();
		$post = array ();
		if (in_array ( $item->get_id (), $post_guids )) {
			continue;
		}
		$news = get_news ( $item->get_id () );
		//提取正文
		if ($news == FALSE) {
			$post_content = $item->get_content ();
			$post_status = $news_args ['no_content_post'];
		} else {
			foreach ( $news_args ['news_pattern'] as $pattern ) {
				if (! $news_args ['auto_matche'] && stripos ( $news, $pattern ['0'] )) {
					preg_match ( $pattern ['1'], $news, $news_matche );
					break;
				} else {
					preg_match ( $pattern ['1'], $news, $news_matche );
				}
			}
			//	    print_r($news_matche);
			if (! empty ( $news_matche )) {
				$post_content = $news_matche ['2'];
				$post_status = $news_args ['has_content_post'];
			} elseif ($item->get_content ()) {
				$post_content = $item->get_content ();
				$post_status = $news_args ['no_content_post'];
			} else {
				continue;
			}
		}
		$post_content = custom_replace ( $post_content, $news_args ['str_replace'], $news_args ['preg_replace'] );
		$post_content = wp_kses ( $post_content, $allowedposttags );
		$post_content = wptexturize ( $post_content );
		$post_content = popuplinks ( $post_content );
		$post_content = make_link_absolute ( $post_content, $item->get_id () );
		if ($news_args ['add_more'] ['0'] && strlen ( $post_content ) > max ( 600, $news_args ['add_more'] ['1'] )) {
			$post_content = substr_replace ( $post_content, '<!--more-->', stripos ( $post_content, '</p>', max ( 300, $news_args ['add_more'] ['2'] ) ) + 4, 0 );
		}
		if ($news_args ['publish_time']) {
			$post_content .= '<br />Published at ' . $item->get_date ( get_option ( 'date_format' ) . ' ' . get_option ( 'time_format' ) ) . ' GMT';
		}
		if ($news_args ['orgin_link']) {
			$post_content .= '<br />From: <a target="_blank"  title="' . $item->get_title () . '" href="' . $item->get_id () . '">' . $item->get_title () . '</a>';
		}
		//	echo $post_content . '<hr />';
		$post_category = term_exists ( $news_args ['category_name'], 'category' );
		if (! $post_category && $news_args ['category_name']) {
			$post_category = wp_insert_term ( $news_args ['category_name'], 'category' );
		}
		$post = array ('post_status' => $post_status, 'post_author' => $news_args ['author'], 'post_category' => $post_category ? array ($post_category ['term_id'] ) : '', 'post_date' => $news_args ['rss_time'] ? $item->get_date () : '', 'post_content' => $post_content, 'post_excerpt' => $item->get_description (), 'post_title' => $item->get_title (), 'tags_input' => '', 'guid' => $item->get_id () );
		generic_ping ( wp_insert_post ( $post ) );
		if (++ $count_post >= $news_args ['news_max']) {
			break;
		}
		sleep ( '1' );
	endforeach
	;
	lock ( 'delete', $news_args ['lock_file'] );
}

/**
 * 添加任务运行时间
 * @package WordPress
 * @subpackage Auto-Post-News
 * @since 0.0.1
 * @param array $schedules 现有时间表
 * @return array $schedules 添加后的计划任务运行时间表
 */
function cron_add_quarter($schedules) {
	$schedules ['apn_quarter'] = array ('interval' => 60 * 15, 'display' => __ ( '15 min' ) );
	return $schedules;
}

/**
 * 插件激活时运行函数,用于添加计划任务
 * @package WordPress
 * @subpackage Auto-Post-News
 * @since 0.0.1
 */
function schedule_post_news() {
	add_filter ( 'cron_schedules', 'cron_add_quarter' );
	if (! wp_next_scheduled ( 'post_news' )) {
		wp_schedule_event ( time (), 'apn_quarter', 'post_news' );
	}
}

/**
 * 禁用插件时执行函数,用于删除任务
 * @package WordPress
 * @subpackage Auto-Post-News
 * @since 0.0.1
 */
function unschedule_post_news() {
	remove_filter ( 'cron_schedules', 'cron_add_quarter' );
	wp_clear_scheduled_hook ( 'post_news' );
	if (file_exists ( dirname ( __FILE__ ) . '/post.lock' )) {
		lock ( 'delete', dirname ( __FILE__ ) . '/post.lock' );
	}
}

function post_news_action() {
	if (time () - wp_next_scheduled ( 'post_news' ) > 900) {
		post_news ();
		wp_reschedule_event ( time (), 'apn_quarter', 'post_news' );
	}
}

register_activation_hook ( __FILE__, 'schedule_post_news' );
register_deactivation_hook ( __FILE__, 'unschedule_post_news' );
add_filter ( 'cron_schedules', 'cron_add_quarter' ); //添加计划任务时间,否则任务会被删除
add_action ( 'post_news', 'post_news' ); //add_action时自动创建post_news action hook
add_action ( 'wp_footer', 'post_news_action' );
?>